package com.ly.dingtalk.service.user.impl;

import com.aliyun.dingtalkcontact_1_0.models.ListEmpLeaveRecordsHeaders;
import com.aliyun.dingtalkcontact_1_0.models.ListEmpLeaveRecordsRequest;
import com.aliyun.dingtalkcontact_1_0.models.ListEmpLeaveRecordsResponse;
import com.aliyun.teautil.models.RuntimeOptions;
import com.dingtalk.api.request.OapiInactiveUserV2GetRequest;
import com.dingtalk.api.request.OapiUserCountRequest;
import com.dingtalk.api.request.OapiUserGetAdminScopeRequest;
import com.dingtalk.api.request.OapiUserGetbyunionidRequest;
import com.dingtalk.api.request.OapiUserListadminRequest;
import com.dingtalk.api.request.OapiUserListidRequest;
import com.dingtalk.api.request.OapiUserListsimpleRequest;
import com.dingtalk.api.request.OapiV2UserCreateRequest;
import com.dingtalk.api.request.OapiV2UserDeleteRequest;
import com.dingtalk.api.request.OapiV2UserGetRequest;
import com.dingtalk.api.request.OapiV2UserGetbymobileRequest;
import com.dingtalk.api.request.OapiV2UserGetuserinfoRequest;
import com.dingtalk.api.request.OapiV2UserListRequest;
import com.dingtalk.api.request.OapiV2UserUpdateRequest;
import com.dingtalk.api.response.OapiInactiveUserV2GetResponse;
import com.dingtalk.api.response.OapiUserCountResponse;
import com.dingtalk.api.response.OapiUserGetAdminScopeResponse;
import com.dingtalk.api.response.OapiUserGetbyunionidResponse;
import com.dingtalk.api.response.OapiUserListadminResponse;
import com.dingtalk.api.response.OapiUserListidResponse;
import com.dingtalk.api.response.OapiUserListsimpleResponse;
import com.dingtalk.api.response.OapiV2UserCreateResponse;
import com.dingtalk.api.response.OapiV2UserDeleteResponse;
import com.dingtalk.api.response.OapiV2UserGetResponse;
import com.dingtalk.api.response.OapiV2UserGetbymobileResponse;
import com.dingtalk.api.response.OapiV2UserGetuserinfoResponse;
import com.dingtalk.api.response.OapiV2UserGetuserinfoResponse.UserGetByCodeResponse;
import com.dingtalk.api.response.OapiV2UserListResponse;
import com.dingtalk.api.response.OapiV2UserUpdateResponse;
import com.ly.dingtalk.common.exception.DingApiException;
import com.ly.dingtalk.common.utils.DingUtils;
import com.ly.dingtalk.component.application.IDingApp;
import com.ly.dingtalk.constant.DingUrlConstant;
import com.ly.dingtalk.constant.Language;
import com.ly.dingtalk.service.AbstractDingNewApi;
import com.ly.dingtalk.service.user.IDingUserNewHandler;
import com.taobao.api.ApiException;

import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class DingUserNewHandler extends AbstractDingNewApi implements IDingUserNewHandler{

    public DingUserNewHandler(IDingApp app) {
        super(app);
    }
    
    

    @Override
    public OapiV2UserGetResponse getUserById(String useId) {
        OapiV2UserGetRequest req = new OapiV2UserGetRequest();
        req.setUserid(useId);
        req.setLanguage(Language.zh_CN.name());
        return execute(
                DingUrlConstant.UserV2.GET_USER_BY_USER_ID,
                req,
                () -> "根据userId查询用户"
        );
    }

    @Override
    public OapiV2UserCreateResponse createUser(OapiV2UserCreateRequest req) {
        return execute(
                DingUrlConstant.UserV2.CREATE_USER,
                req,
                () -> "创建用户"
        );
    }
    
    @Override
    public OapiV2UserDeleteResponse deleteUserById(String userId) {
        OapiV2UserDeleteRequest req = new OapiV2UserDeleteRequest();
        req.setUserid(userId);
        return execute(
                DingUrlConstant.UserV2.DELETE_USER,
                req,
                () -> "删除用户"
        );
    }

    @Override
    public OapiV2UserUpdateResponse updateUserById(OapiV2UserUpdateRequest req) {
        return execute(
                DingUrlConstant.UserV2.UPDATE_USER,
                req,
                () -> "更新用户"
        );
    }

    /**
     * OapiUserListsimpleRequest.setDeptId(部门id)
     * @see com.ly.dingtalk.service.user.IDingUserNewHandler#listsimple(com.dingtalk.api.request.OapiUserListsimpleRequest)
     */
    @Override
    public OapiUserListsimpleResponse listsimple(OapiUserListsimpleRequest req) {
        return execute(
                DingUrlConstant.UserV2.LISTS_IMPLE,
                req,
                () -> "查询部门员工的简单信息"
        );
    }

    /**
     * @param deptId 根部门是1
     * @see com.ly.dingtalk.service.user.IDingUserNewHandler#listid(java.lang.Long)
     */
    @Override
    public OapiUserListidResponse listid(Long deptId) {
        OapiUserListidRequest req = new OapiUserListidRequest();
        req.setDeptId(deptId);
        return execute(
                DingUrlConstant.UserV2.LIST_ID,
                req,
                () -> "查询部门员工的id"
        );
    }

    @Override
    public OapiV2UserListResponse list(OapiV2UserListRequest req) {
        return execute(
                DingUrlConstant.UserV2.LIST,
                req,
                () -> "查询部门员工"
        );
    }

    /**
     * @param onlyActive 是否包含未激活钉钉人数, false：包含未激活钉钉的人员数量。
     * @see com.ly.dingtalk.service.user.IDingUserNewHandler#count(java.lang.Boolean)
     */
    @Override
    public OapiUserCountResponse count(Boolean onlyActive) {
        OapiUserCountRequest req = new OapiUserCountRequest();
        req.setOnlyActive(onlyActive);
        return execute(
                DingUrlConstant.UserV2.COUNT,
                req,
                () -> "查询人员数量"
        );
    }
    
    /**
     * 调用本接口查询指定日期内未登录钉钉的企业员工列表。
     * 每天9点后调用接口才能确保获取前一天数据。
     * 调用本接口只能获取一个月内未登录钉钉的员工列表。
     * @see com.ly.dingtalk.service.user.IDingUserNewHandler#getInactive(com.dingtalk.api.request.OapiInactiveUserV2GetRequest)
     */
    @Override
    public OapiInactiveUserV2GetResponse getInactive(OapiInactiveUserV2GetRequest req) {
        return execute(
                DingUrlConstant.UserV2.GET_INACTIVE,
                req,
                () -> "指定日期内未登入钉钉的员工"
        );
    }
    
    /**
     * @Description: TODO 普通员工返回普通员工的id, 如果他有企业账号也会返回企业账号id
     * @see com.ly.dingtalk.service.user.IDingUserNewHandler#getbymobile(com.dingtalk.api.request.OapiV2UserGetbymobileRequest)
     */
    @Override
    public OapiV2UserGetbymobileResponse getbymobile(OapiV2UserGetbymobileRequest req) {
        return execute(
                DingUrlConstant.UserV2.GET_BY_MOBILE,
                req,
                () -> "根据手机号查用户信息"
        );
    }

    /**
     * 
     * @Description: 根据unionid获取用户的userid。
     * unionid是员工在当前开发者企业账号范围内的唯一标识，由系统生成：
     *   同一个企业员工，在不同的开发者企业账号下，unionid是不相同的。
     *   在同一个开发者企业账号下，unionid是唯一且不变的，例如同一个服务商开发的多个应用，或者是扫码登录等场景的多个App账号。
     *   https://open.dingtalk.com/document/orgapp/obtain-the-userid-of-a-user-by-using-the-log-free?spm=ding_open_doc.document.0.0.184b3f20S8oLeT
     * @see com.ly.dingtalk.service.user.IDingUserNewHandler#getbyunionid(com.dingtalk.api.request.OapiUserGetbyunionidRequest)
     */
    @Override
    public OapiUserGetbyunionidResponse getbyunionid(OapiUserGetbyunionidRequest req) {
        return execute(
                DingUrlConstant.UserV2.GET_BY_UNIONID,
                req,
                () -> "根据unionid获取用户信息"
        );
    }
    
    @Override
    public OapiUserListadminResponse listadmin(OapiUserListadminRequest req) {
        return execute(
                DingUrlConstant.UserV2.LIST_ADMIN,
                req,
                () -> "获取管理员列表"
        );
    }
    
    @Override
    public OapiUserGetAdminScopeResponse getAdminScope(OapiUserGetAdminScopeRequest req) {
        return execute(
                DingUrlConstant.UserV2.GET_ADMIN_SCOPE,
                req,
                () -> "获取管理员通讯录权限范围"
        );
    }
    
    /**
     * 需要权限
     * https://open-dev.dingtalk.com/fe/ai#/app/46a2c0db-9222-4576-8e87-7bc47dfedbce/permission
     * 权限管理->通讯录管理->第二页找到  通讯录基本数据读权限  申请下权限就可以了额
     * @see com.ly.dingtalk.service.user.IDingUserNewHandler#empLeaveRecords(com.aliyun.dingtalkcontact_1_0.models.ListEmpLeaveRecordsRequest)
     */
    @Override
    public ListEmpLeaveRecordsResponse empLeaveRecords(ListEmpLeaveRecordsRequest req) {
        return execute(com.aliyun.dingtalkcontact_1_0.Client.class, client -> {
            ListEmpLeaveRecordsResponse listEmpLeaveRecordsWithOptions = null;
            try {
                ListEmpLeaveRecordsHeaders listEmpLeaveRecordsHeaders = new ListEmpLeaveRecordsHeaders();
                listEmpLeaveRecordsHeaders.xAcsDingtalkAccessToken = accessToken();
                config.protocol = "https";
                config.regionId = "central";
                listEmpLeaveRecordsWithOptions = client.listEmpLeaveRecordsWithOptions(req, listEmpLeaveRecordsHeaders, new RuntimeOptions());
            } catch (Exception e) {
                log.error("钉钉请求异常: " + e.getMessage(), e);
                throw new DingApiException(e.getMessage());
            }
            return listEmpLeaveRecordsWithOptions;
        }, () -> "查询离职记录列表");
    }

    /**
     * com.ly.dingtalk.service.login.DingLoginHandler.getUserToken(String, GrantType)
     * @Description: 会在登入的时候用的到, 登入的时候有authCode,获取用户信息
     * @see com.ly.dingtalk.service.user.IDingUserNewHandler#findUserByLoginAuthCode(java.lang.String)
     * @date 2023-12-27 09:44:49
     */
    @Override
    public UserGetByCodeResponse findUserByLoginAuthCode(@NonNull String authCode) {
        OapiV2UserGetuserinfoRequest request = new OapiV2UserGetuserinfoRequest();
        request.setCode(authCode);
        OapiV2UserGetuserinfoResponse response = execute(
                DingUrlConstant.User.GET_USER_BY_LOGIN_AUTH_CODE,
                request,
                resp -> {
                    try {
                        DingUtils.UserResponse.isOk(resp);
                    } catch (ApiException e) {
                        log.error("根据authCode获取钉钉用户响应失败", e);
                        throw new DingApiException("根据authCode获取钉钉用户响应失败");
                    }
                },
                () -> "根据authCode获取钉钉用户"
        );
        return response.getResult();
    }

}
